package org.springblade.modules.mes.quality.utils;

import org.springblade.core.tool.utils.CollectionUtil;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class CalSta {

    public static double sum(double[] data) {
        double sum = 0;
        for (int i = 0; i < data.length; i++)
            sum = sum + data[i];
        return sum;
    }

    public static double max(double[] data) {
        double sum = 0;
        for (int i = 0; i < data.length; i++)
            sum = sum + data[i];
        return sum;
    }

    public static double mean(double[] data) {
        double mean = 0;
        mean = sum(data) / data.length;
        return mean;
    }

    //总体方差
    public static double popVariance(double[] data) {
        double variance = 0;
        for (int i = 0; i < data.length; i++) {
            variance = variance + (Math.pow((data[i] - mean(data)), 2));
        }
        variance = variance / data.length;
        return variance;
    }

    //总体标准差
    public static double popStdDev(double[] data) {
        double std_dev;
        std_dev = Math.sqrt(popVariance(data));
        return std_dev;
    }

    //样本方差
    public static double sampleVariance(double[] data) {
        double variance = 0;
        for (int i = 0; i < data.length; i++) {
            variance = variance + (Math.pow((data[i] - mean(data)), 2));
        }
        variance = variance / (data.length - 1);
        return variance;
    }

    //样本标准差
    public static double sampleStdDev(double[] data) {
        double std_dev;
        std_dev = Math.sqrt(sampleVariance(data));
        return std_dev;
    }

    // sample standard deviation 频次
    public static int frequency(double[] a, double max, double min) {
        int i = 0;
        for (double d : a) {
            if (max == min) {
                if (d <= min) {
                    ++i;
                }
            } else {
                if (d > min && d <= max) {
                    ++i;
                }
            }
        }
        return i;
    }

    //
//    public static double normal(double x, double mean, double standard_dev) {
//        return new NormalDistribution(mean, standard_dev).density(x);
//    }

    public static double round(double x) {
        return (double) Math.round(x * 100) / 100;
    }

    public  static Map<String,Object> getNormal(List<String> xList){
        Map<String,Object> map=new HashMap<>();
        List<Double> doubleList = xList.stream().map(Double::parseDouble).collect(Collectors.toList());
        double[] data = doubleList.stream().mapToDouble(Double::doubleValue).toArray();
        double avg = 0;
        double min = 0;
        double max = 0;
        double sigma = 0;
        int z = 4;
        double z2 = 0.4;
        if (CollectionUtil.isNotEmpty(doubleList)) {
            max = doubleList.stream().mapToDouble(Double::doubleValue).max().getAsDouble();
            avg = mean(data);
            min = doubleList.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
            sigma = sampleStdDev(data);
        }
        double cpk1 = 0;
        double cp1 = 0;
        if (sigma != 0) {
            cpk1 = Math.min((max - avg), (avg - min)) / (3 * sigma);
            cp1 = (max - min) / (6 * sigma);
        }
        //分22组数据
        List<Double[]> frequencyArrList = new LinkedList<>();
        List<Double[]> normdistArrList = new LinkedList<>();
        for (int i = 0; i < 22; i++) {
            double groupData1 = 0;
            if (z > 0) {
                groupData1 = avg - sigma * (z - i * 0.4);
            } else if (z == 0) {
                groupData1 = avg;
            } else {
                groupData1 = avg - sigma * (z2 + (i - 9) * 0.4);
            }
            z += 0.4;
            int frenum1 = 0;
            if (i == 0) {
                frenum1 = frequency(data, groupData1, groupData1);
            } else {
                frenum1 = frequency(data, groupData1, frequencyArrList.get(i - 1)[0]);
            }
            double normdist1 = 0;
            if (sigma != 0) {
//                normdist1 = normal(groupData1, avg, sigma);
            }
            Double[] s1 = new Double[2];
            s1[0] = round(groupData1);
            s1[1] = Double.parseDouble(String.valueOf(frenum1));
            frequencyArrList.add(s1);
            Double[] s2 = new Double[2];
            s2[0] = round(groupData1);
            s2[1] = round(normdist1 * 100);
            normdistArrList.add(s2);
        }
        map.put("x3s1", avg - sigma * 3);
        map.put("x3s2", avg + sigma * 3);
        map.put("frequencyArrList", frequencyArrList);
        map.put("normdistArrList", normdistArrList);
        map.put("cp", cp1);
        map.put("cpk", cpk1);
        map.put("sigma", sigma);
        map.put("avg", avg);
        map.put("ybsl", xList.size());
        map.put("max", max);
        map.put("min", min);
        return map;
    }
}
